package com.cvte.boe.media.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.media.MediaMetadataRetriever;
import android.view.View;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class BitmapUtils {

    private final static String TAG = "BitmapUtils";

    /**
     * 读取图片Bitmap，并压缩
     *
     * @param path 图片路径
     * @return
     */
    public static Bitmap comp(String path) {
        File file = new File(path);
        if (file == null || !file.exists()) return null;
        BitmapFactory.Options localOptions = new BitmapFactory.Options();
        localOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        localOptions.inPurgeable = true;
        localOptions.inInputShareable = true;
        try {
            return BitmapFactory.decodeStream(new FileInputStream(path), null, localOptions);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Bitmap comp(String path, float width, float height) {
        File file = new File(path);
        if (file == null || !file.exists()) return null;

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 获取这个图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile(path, options); //此时返回bm为空
        options.inJustDecodeBounds = false;


        BitmapFactory.Options localOptions = new BitmapFactory.Options();
        localOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        localOptions.inPurgeable = true;
        localOptions.inInputShareable = true;
        int be1 = (int)(options.outHeight / (float)height);
        int be2 = (int)(options.outWidth / (float)width);
        int be = Math.min(be1, be2);
        if (be <= 0)
            be = 1;
        localOptions.inSampleSize = be;
        try {
            return BitmapFactory.decodeStream(new FileInputStream(path), null, localOptions);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 不占内存获取路径图片的压缩比例
     *
     * @param width    压缩到指定宽度
     * @param height   压缩到指定高度
     * @return
     */
    public static int getInSampleSize(String path, float width, float height) {
        File file = new File(path);
        if (file == null || !file.exists()) return -1;

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 获取这个图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile(path, options); //此时返回bm为空

        int inSampleSize1 = (int)(options.outHeight / (float)height);
        int inSampleSize2 = (int)(options.outWidth / (float)width);
        int inSampleSize = Math.min(inSampleSize1, inSampleSize2);
        if (inSampleSize <= 0)
            inSampleSize = 1;

        return inSampleSize;
    }

    /**
     * 图片压缩
     *
     * @param context
     * @param resId   图片资源ID
     * @return
     */
    public static Bitmap comp(Context context, int resId) {
        BitmapFactory.Options localOptions = new BitmapFactory.Options();
        localOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        localOptions.inPurgeable = true;
        localOptions.inInputShareable = true;
        return BitmapFactory.decodeStream(context.getResources().openRawResource(resId), null, localOptions);
    }

    /**
     * 图片压缩
     *
     * @param context
     * @param resId   图片资源ID
     * @param w
     * @param h
     * @return
     */
    public static Bitmap comp(Context context, int resId, int w, int h) {
        BitmapFactory.Options localOptions = new BitmapFactory.Options();
        localOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        localOptions.inPurgeable = true;
        localOptions.inInputShareable = true;
        return comp(BitmapFactory.decodeStream(context.getResources().openRawResource(resId), null, localOptions), w, h);
    }

    /**
     * 图片宽高比例压缩
     *
     * @param bgimage
     * @param newWidth
     * @param newHeight
     * @return
     */
    public static Bitmap comp(Bitmap bgimage, int newWidth, int newHeight) {
        float width = bgimage.getWidth();
        float height = bgimage.getHeight();
        Matrix matrix = new Matrix();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        matrix.postScale(scaleWidth, scaleHeight);
        return Bitmap.createBitmap(bgimage, 0, 0, (int) width, (int) height, matrix, true);
    }

    /**
     * 获取View截图
     *
     * @param view
     * @return
     */
    public static Bitmap convertViewToBitmap(View view) {
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        return bitmap;
    }


    /**
     * 按显示质量压缩Bitmap图片大小
     *
     * @param bmp
     */
    public static Bitmap compressBitmap(Bitmap bmp) {
        try {
            int memTotal = MemInfoUtil.getInstance().getIntMemInfo("MemTotal") / 1024;
            int limitSize = memTotal <= 512 ? 50 : (memTotal <= 768 ? 60 : (memTotal <= 1024 ? 75 : 100));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int options = 80;
            bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
            while (baos.toByteArray().length / 1024 > limitSize) {
                baos.reset();
                options -= 10;
                if (options <= 0)
                    break;
                bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
            }
            ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
            Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bmp;
    }

    /**
     * 按比例大小压缩方法
     *
     * @param bmp
     * @param maxWidth
     * @param maxHeight
     * @return
     */
    public static Bitmap compressBitmap(Bitmap bmp, int maxWidth, int maxHeight) {
        if (maxWidth <= 0 || maxHeight <= 0)
            return bmp;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        if (baos.toByteArray().length / 1024 > 1024) {
            baos.reset();//重置baos即清空baos
            bmp.compress(Bitmap.CompressFormat.JPEG, 50, baos);
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        int be = 1;
        if (w > h && w > maxWidth) {
            be = newOpts.outWidth / maxWidth;
        } else if (w < h && h > maxHeight) {
            be = newOpts.outHeight / maxHeight;
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;
        isBm = new ByteArrayInputStream(baos.toByteArray());
        bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
        return compressBitmap(bitmap);
    }

    /**
     * 根据Bitmap生成倒影截图
     *
     * @param srcBitmap
     * @param reflectHeight
     * @return
     */
    public static Bitmap createReflectedBitmap(Bitmap srcBitmap,
                                               float reflectHeight) {
        if (null == srcBitmap) {
            return null;
        }

        int srcWidth = srcBitmap.getWidth();
        int srcHeight = srcBitmap.getHeight();
        int reflectionWidth = srcBitmap.getWidth();
        int reflectionHeight = reflectHeight == 0 ? srcHeight / 3
                : (int) (reflectHeight * srcHeight);

        if (0 == srcWidth || srcHeight == 0) {
            return null;
        }

        // The matrix
        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);

        try {
            // The reflection bitmap, width is same with original's
            Bitmap reflectionBitmap = Bitmap.createBitmap(srcBitmap, 0,
                    srcHeight - reflectionHeight, reflectionWidth,
                    reflectionHeight, matrix, false);

            if (null == reflectionBitmap) {
                return null;
            }

            Canvas canvas = new Canvas(reflectionBitmap);

            Paint paint = new Paint();
            paint.setAntiAlias(true);

            LinearGradient shader = new LinearGradient(0, 0, 0,
                    reflectionBitmap.getHeight(), 0x70FFFFFF, 0x00FFFFFF,
                    Shader.TileMode.MIRROR);
            paint.setShader(shader);

            paint.setXfermode(new PorterDuffXfermode(
                    android.graphics.PorterDuff.Mode.DST_IN));

            // Draw the linear shader.
            canvas.drawRect(0, 0, reflectionBitmap.getWidth(),
                    reflectionBitmap.getHeight(), paint);

            return reflectionBitmap;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 根据视频文件按帧获取第几秒的截图
     *
     * @param path
     * @param second
     * @return
     */
    public static Bitmap getBitmapByVideo(String path, int second) {
        try {
            File file = new File(path);
            if (file.exists() && file.isFile()) {
                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                retriever.setDataSource(path);
                // 取得视频的长度(单位为毫秒)
                String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                int seconds = Integer.valueOf(time) / 1000;
                if (second > 0 && second <= seconds) {
                    return retriever.getFrameAtTime(second * 1000 * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据视频文件随机获取第几秒的截图
     *
     * @param path
     * @return
     */
    public static Bitmap getBitmapByVideo(String path) {
        try {
            File file = new File(path);
            if (file.exists() && file.isFile()) {
                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                retriever.setDataSource(path);
                // 取得视频的长度(单位为毫秒)
                String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                int seconds = Integer.valueOf(time) / 1000;
                int second = RandomUtils.getRandom(seconds);
                if (second > 0 && second <= seconds) {
                    return retriever.getFrameAtTime(second * 1000 * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Bitmap createBitmapforListIcon(String url, int paramInt1, int paramInt2) {
        try {
            BitmapFactory.Options localOptions = new BitmapFactory.Options();
            localOptions.inPurgeable = true;
            localOptions.inInputShareable = true;
            localOptions.inTempStorage = new byte[16384];
            localOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(url, localOptions);
            localOptions.inSampleSize = computeSampleSize(localOptions, -1, paramInt1 * paramInt2);
            localOptions.inJustDecodeBounds = false;
            LogUtil.d(TAG, "opts.inSampleSize=" + localOptions.inSampleSize);
            return BitmapFactory.decodeFile(url, localOptions);
        } catch (OutOfMemoryError localOutOfMemoryError) {
            System.gc();
            localOutOfMemoryError.printStackTrace();
            LogUtil.w(TAG, "BitmapFactory.decodeFile OutOfMemoryError!!!");
            Bitmap localBitmap1 = null;
        }
        return null;
    }

    public static Bitmap createBitmapFromNetwork(String url, int w, int h) {
        InputStream inputStream = null;
        Bitmap bitmap = null;
        try {
            LogUtil.d(TAG, String.format("createBitmapFromNetwork url: %s", url));
            if (!StringUtils.isEmpty(url) && StringUtils.isNetworkURI(url)) {
                URL mUrl = new URL(url);
                HttpURLConnection conn = (HttpURLConnection) mUrl.openConnection();
                conn.setConnectTimeout(10000);
                conn.setReadTimeout(10000);
                conn.setRequestMethod("GET");
                conn.setDoInput(true);
                if (conn.getResponseCode() == 200) {
                    inputStream = conn.getInputStream();
                    if (inputStream != null) {
                        BitmapFactory.Options opts = new BitmapFactory.Options();
                        opts.inPurgeable = true;
                        opts.inInputShareable = true;
                        opts.inTempStorage = new byte[16384];
                        opts.inJustDecodeBounds = true;
                        opts.inJustDecodeBounds = true;
                        LogUtil.d(TAG, "opts.inSampleSize=" + opts.inSampleSize);
                        bitmap = BitmapFactory.decodeStream(inputStream, null, opts);
                        if (!isWithinBitmapCapacity(opts)) {
                            opts.inSampleSize = computeSampleSize(opts, -1, w * h);
                            opts.inJustDecodeBounds = false;
                            bitmap = BitmapFactory.decodeStream(inputStream, null, opts);
                        }
                        conn.disconnect();
                        inputStream.close();
                    }
                }
                return bitmap;
            }
        } catch (OutOfMemoryError ex) {
            System.gc();
            ex.printStackTrace();
            LogUtil.w(TAG, "BitmapFactory.decodeFile OutOfMemoryError!!!");
        } catch (MalformedURLException me) {
            me.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static int computeInitialSampleSize(BitmapFactory.Options paramOptions, int minSideLength, int maxNumOfPixels) {
        double d1 = paramOptions.outWidth;
        double d2 = paramOptions.outHeight;
        int lowerBound = 1;
        int upperBound = 128;
        if (maxNumOfPixels != -1) {
            lowerBound = (int) Math.ceil(Math.sqrt(d1 * d2 / maxNumOfPixels));
        }
        if (minSideLength != -1) {
            upperBound = (int) Math.min(Math.floor(d1 / minSideLength), Math.floor(d2 / minSideLength));
        }
        if (upperBound >= lowerBound) {
            if (minSideLength != -1 || maxNumOfPixels != -1) {
                lowerBound = upperBound;
                return lowerBound;
            }
        }
        return lowerBound;
    }

    public static int computeSampleSize(BitmapFactory.Options paramOptions, int paramInt) {
        int i = paramOptions.outWidth;
        int j = paramOptions.outHeight;
        int k = Math.max(i / paramInt, j / paramInt);
        if (k == 0)
            k = 1;
        return k;
    }

    public static int computeSampleSize(BitmapFactory.Options paramOptions, int paramInt1, int paramInt2) {
        int i = computeInitialSampleSize(paramOptions, paramInt1, paramInt2);
        int j = 8 * ((i + 7) / 8);
        if (i <= 8) {
            j = 1;
            while (j < i)
                j <<= 1;
        }
        return j;
    }

    public static boolean isWithinBitmapCapacity(int w, int h) {
        return w * h <= 64000000L;
    }

    public static boolean isWithinBitmapCapacity(BitmapFactory.Options opts) {
        if (opts != null)
            return isWithinBitmapCapacity(opts.outWidth, opts.outHeight);
        LogUtil.e(TAG, "isWithinBitmapCapacity opt is null");
        return false;
    }

    /**
     * 获取圆角图片
     *
     * @param bitmap
     * @param xy_radius
     * @return
     */
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float xy_radius) {
        if (bitmap != null) {
            Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                    bitmap.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
            final int color = 0xff424242;
            final Paint paint = new Paint();
            final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
            final RectF rectF = new RectF(rect);
            final float roundPx = xy_radius;
            paint.setAntiAlias(true);
            canvas.drawARGB(0, 0, 0, 0);
            paint.setColor(color);
            canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawBitmap(bitmap, rect, rect, paint);
            return output;
        }
        return null;
    }

    /**
     * 获取裁剪大小并画圆角的图片
     *
     * @param bitmap
     * @param xy_radius
     * @return
     */
    public static Bitmap getRoundedCornerAndCutBitmap(Bitmap bitmap, float xy_radius, int cutXPosition, int cutYposition,
                                                      int cutWidth, int cutHeight) {

        if (bitmap != null) {
            Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                    bitmap.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
            final int color = 0xff424242;
            final int color1 = 0xffffffff;
            final Paint paint = new Paint();

            final Rect rect;
            rect = new Rect(cutXPosition, cutYposition, bitmap.getWidth() - cutWidth , bitmap.getHeight() - cutHeight);
            final Rect rectBitmap = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
            final RectF rectF = new RectF(rect);
            final float roundPx = xy_radius;
            paint.setAntiAlias(true);
            canvas.drawARGB(0, 0, 0, 0);
            paint.setColor(color1);
            canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawBitmap(bitmap, rect, rectBitmap, paint);
            return output;
        }
        return null;
    }

    /**
     * 获取圆角图片
     *
     * @param bitmap
     * @param x_radius
     * @param y_radius
     * @return
     */
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float x_radius, float y_radius) {
        if (bitmap != null) {
            Bitmap localBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas localCanvas = new Canvas(localBitmap);
            Paint localPaint = new Paint();
            Rect localRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
            RectF localRectF = new RectF(localRect);
            localPaint.setAntiAlias(true);
            localCanvas.drawARGB(0, 0, 0, 0);
            localPaint.setColor(Color.TRANSPARENT);
            localCanvas.drawRoundRect(localRectF, x_radius, y_radius, localPaint);
            localPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            localCanvas.drawBitmap(bitmap, localRect, localRect, localPaint);
            return localBitmap;
        }
        return null;
    }
}
